/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
 *
 */

import path from 'path';

import { HvigorCommonConst, Module } from '@ohos/hvigor';

import { findTargetProduct } from '../../common/find-target-product.js';
import {DefaultTargetConst} from '../../const/common-const.js';
import { ModuleType } from '../../enum/module-type-enum.js';
import {ProjectBuildProfile} from '../../options/build/project-build-profile.js';
import { ModuleJson } from '../../options/configure/module-json-options.js';
import { getElementFromArr } from '../../utils/array-util.js';
import { OhosLogger } from '../../utils/log/ohos-logger.js';
import { isAtomicServiceProject } from '../../utils/task-util.js';
import { ValidateUtil } from '../../utils/validate/validate-util.js';
import { ProjectModel } from '../project/project-model.js';
import { TargetSourceSetModel } from '../source-set/source-set-model.js';
import { TargetSourceSetImpl } from '../source-set/target-source-set-impl.js';
import { CoreModuleModelImpl } from './core-module-model-impl.js';

import ModuleOptObj = ModuleJson.ModuleOptObj;

const defaultTargetName = DefaultTargetConst.DEFAULT_TARGET;
const ohosTestTargetName = DefaultTargetConst.OHOS_TEST_TARGET;
const _log = OhosLogger.getLogger('moduleModel');

/**
 * hvigor 工程的module模块的数据管理对象
 *
 * @since 2022/2/23
 */
export class ModuleModelImpl extends CoreModuleModelImpl {
  constructor(module: Module, parentProject: ProjectModel) {
    super(module, parentProject);
    this.initDefaultTargetSourceSet();
  }

  getDeviceTypes(): string[] {
    const deviceTypes = this.getSourceSetByTargetName().getModuleTargetRes().getModuleJsonOpt()?.module.deviceTypes;
    if (deviceTypes === null || deviceTypes === undefined) {
      _log.printErrorExit(
        'DEVICE_TYPE_NOT_FOUND_STAGE',
        [],
        [[this.getSourceSetByTargetName().getModuleTargetRes().getJsonPath()]]
      );
    }
    return deviceTypes;
  }

  initDefaultTargetSourceSet() {
    // 初始化创建default的target sourceSet
    const defaultTargetSourceSet = new TargetSourceSetImpl(path.resolve(this._sourceRootDir, 'main'));
    this.targetSourceSetMap.set(defaultTargetName, defaultTargetSourceSet);

    // 若有配置ohosTest target
    const ohosTestTarget = getElementFromArr(this.getProfileOpt().targets, ohosTestTargetName);
    if (ohosTestTarget) {
      const ohosTestTargetSourceSet = new TargetSourceSetImpl(path.resolve(this._sourceRootDir, ohosTestTargetName));
      this.targetSourceSetMap.set(ohosTestTargetName, ohosTestTargetSourceSet);
    }
  }

  getModuleType(): ModuleType {
    const targetSourceSetImpl = this.getSourceSetByTargetName() as TargetSourceSetImpl;
    if (!targetSourceSetImpl) {
      _log.printErrorExit(
        'STAGE_NO_SYSTEM_PLUGIN',
        [`${path.resolve(this.getProjectDir(), HvigorCommonConst.BUILD_FILE_NAME)}.ts`],
        [[`${path.resolve(this.getProjectDir(), HvigorCommonConst.BUILD_FILE_NAME)}.ts`]]
      );
    }

    const moduleJsonOpt: ModuleOptObj = targetSourceSetImpl.getModuleTargetRes().getModuleJsonOpt();
    if (moduleJsonOpt === undefined) {
      _log.printErrorExit('MODULEJSON5_FILE_NOT_FOUND', [], [[targetSourceSetImpl.getModuleTargetRes().getJsonPath()]]);
    }

    if (moduleJsonOpt.module === undefined) {
      _log.printErrorExit(
        'NO_MODULE_INFORMATION',
        [targetSourceSetImpl.getModuleTargetRes().getJsonPath()],
        [[targetSourceSetImpl.getModuleTargetRes().getJsonPath()]]
      );
    }

    if (moduleJsonOpt.module.type === undefined) {
      _log.printErrorExit(
        'NO_MODULE_TYPE',
        [targetSourceSetImpl.getModuleTargetRes().getJsonPath()],
        [[targetSourceSetImpl.getModuleTargetRes().getJsonPath()]]
      );
    }
    return ModuleType.valueOf(moduleJsonOpt.module.type);
  }

  getSourceSetByTargetName(targetName: string = defaultTargetName): TargetSourceSetModel {
    if (this.targetSourceSetMap.has(targetName)) {
      return this.targetSourceSetMap.get(targetName)! as TargetSourceSetImpl;
    }
    return this.targetSourceSetMap.get(defaultTargetName)! as TargetSourceSetImpl;
  }

  getJsonObjByTargetName(targetName: string): ModuleJson.ModuleOptObj {
    return this.getSourceSetByTargetName(targetName).getModuleTargetRes().getModuleJsonOpt();
  }

  getJsonPathByTargetName(targetName: string): string {
    return this.getSourceSetByTargetName(targetName).getModuleTargetRes().getJsonPath();
  }

  isAtomicService(): boolean {
    const product: ProjectBuildProfile.ProductBuildOpt = findTargetProduct(this.getParentProject());
    return isAtomicServiceProject(product, this.getParentProject());
  }

  isInstallFree(): boolean {
    return this.getJsonObjByTargetName(defaultTargetName).module.installationFree || false;
  }

  /**
   * 根据模块的target和存储卡片信息的文件路径得到卡片信息
   *
   * @param targetName 模块的target名
   * @param formPath 存储卡片信息的文件路径
   * @return ModuleJson.FormsObj 存储卡片们的信息的对象
   */
  getFormJsonObjByTargetName(targetName: string, formPath: string): ModuleJson.FormsObj {
    const formsObj = this.getSourceSetByTargetName(targetName).getModuleTargetRes().getFormJsonOpt(formPath);
    ValidateUtil.validateDuplicatedName(formsObj.forms, 'Form', formPath);
    const formJsonPath = path.resolve(this.getSourceSetByTargetName(targetName).getModuleTargetRes().getResourcePath(), formPath);
    ValidateUtil.isDefaultCheck(formsObj.forms, formJsonPath);
    ValidateUtil.checkUpdateEnable(formsObj.forms, formJsonPath);
    return formsObj;
  }

  getPermission(): object {
    const moduleJsonObj: ModuleJson.ModuleOptObj = this.getSourceSetByTargetName().getModuleTargetRes().getModuleJsonOpt();
    return {
      requestPermissions: moduleJsonObj.module.requestPermissions,
      definePermissions: moduleJsonObj.module.definePermissions,
    };
  }

  getCompressNativeLib() {
    const moduleJsonObj: ModuleJson.ModuleOptObj = this.getSourceSetByTargetName().getModuleTargetRes().getModuleJsonOpt();
    return moduleJsonObj.module.compressNativeLibs;
  }
}
